package com.ueboot.weishop.api.controller.weixin;

import com.ueboot.core.utils.WXUtil;
import com.ueboot.core.utils.XMLUtil;
import com.ueboot.weishop.api.mq.config.QueuesType;
import com.ueboot.weishop.service.common.PropertiesService;
import com.ueboot.weishop.service.order.OrderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * 微信支付-回调接口
 *
 * @author yangkui
 */
@Controller
@RequestMapping("/api/public/wxpay/")
public class WeixinPayNoticeController {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private PropertiesService propertiesService;
    /**
     * 微信下单时的订单附加值
     */
    public static final String ORDER_ATTACH = "weishop";

    @Autowired
    private OrderService orderService;

    @Autowired
    private AmqpTemplate amqpTemplate;


    /***
     * 付款成功回调处理
     * <p/>
     *
     * @throws IOException
     * @modify 阳葵 调整部分判断，增加业务逻辑
     */
    @RequestMapping(value = "/notify")
    @ResponseBody
    public void notifySuccess(HttpServletRequest request,
                              HttpServletResponse response) throws IOException {
        log.info("接收到支付回调请求");
        InputStream inStream = request.getInputStream();
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        Integer len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        outSteam.close();
        inStream.close();

        /* 支付成功后，微信回调返回的信息 */
        String result = new String(outSteam.toByteArray(), "utf-8");
        log.info("微信返回的订单支付信息:{}", result);
        Map<String, String> map = XMLUtil.doXMLParse(result);

        // 用于验签
        SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        for (Object keyValue : map.keySet()) {
            if (!"sign".equals(keyValue)) {
                parameters.put(keyValue, map.get(keyValue));
            }
        }
        if (map.get("result_code").equalsIgnoreCase("SUCCESS")) {

            // 先进行校验，是否是微信服务器返回的信息
            String checkSign = WXUtil.createSign("UTF-8", parameters, propertiesService.getWeiXinPayAppKey());
            log.info("请求签名：{}，本机计算签名:{}", map.get("sign"), checkSign);
            if (checkSign.equals(map.get("sign"))) {// 如果签名和服务器返回的签名一致，说明数据没有被篡改过
                //订单号
                String orderNo = map.get("out_trade_no");
                //附加参数
                String attach = map.get("attach");
                //微信平台交易号
                String transactionId = map.get("transaction_id");

                /* 告诉微信服务器，我收到信息了，不要再调用回调方法了 */
                /*如果不返回SUCCESS的信息给微信服务器，则微信服务器会在一定时间内，多次调用该回调方法，如果最终还未收到回馈，微信默认该订单支付失败*/
                /* 微信默认会调用8次该回调地址 */
                // 处理业务逻辑
                if (ORDER_ATTACH.equals(attach)) {
                    log.info("业务订单:{}开始处理回调事情!", orderNo);
                    //调用订单处理接口实现订单状态更新
                    orderService.updateOrderStatusAndPayNotice(orderNo, transactionId);
                    //MQ通知，其他业务处理
                    amqpTemplate.convertAndSend(QueuesType.ORDER_PAYED_NOTICE, orderNo);
                    log.info("发送ORDER_PAYED_NOTICE MQ完成!");
                    String xml = WXUtil.setResponseXML("SUCCESS", "");
                    response.getWriter().write(xml);
                    log.info("返回给微信服务接口报文:{}", xml);
                } else {
                    log.info("业务订单:{} attach不符，不处理", orderNo);
                }

            } else {
                log.error("支付回调结果为不成功，签名结果不一致!请求签名：{}，本机计算签名:{}", map.get("sign"), checkSign);
                response.getWriter().write(WXUtil.setResponseXML("FAIL", "支付回调结果为不成功，签名结果不一致"));
            }
        } else {
            log.error("支付回调结果为不成功，错误信息为：{}!", parameters.get("return_msg"));
            response.getWriter().write(WXUtil.setResponseXML("FAIL", ""));
        }

    }

    /***
     * 付款成功回调处理-模拟支付成功，开奖逻辑
     * <p/>
     *
     * @throws IOException
     * @modify 阳葵 调整部分判断，增加业务逻辑
     */
    @RequestMapping(value = "/notifyPayed/{pass}/{orderNo}")
    @ResponseBody
    public String notifyPayed(@PathVariable String orderNo,@PathVariable String pass) throws IOException {
        if(!("QWE123").equals(pass)){
            log.info("密码错误");
            return "error";
        }
        amqpTemplate.convertAndSend(QueuesType.ORDER_PAYED_NOTICE, orderNo);
        log.info("已经通知MQ");
        return orderNo;

    }

}
